package main

import (
	"fmt"
	"math"
	"math/cmplx"
)

// 包内变量的定义
var aa = 11

var ss = "123"

//bb := 123 // 在函数外定义变量必须使用var关键字

// 但是包内变量可以放到一个括号中
var (
	cc = 3
	dd = "kkk"
	ee = true
)

// 变量有默认初始值
func variableZeroValue() {
	var a int
	var s string
	fmt.Printf("%d %q\n", a, s)
}

// 变量可以赋初始值
func variableInitialValue() {
	var a, b = 3, 4
	var s = "abc"
	fmt.Println(a, b, s)
}

// 变量可根据值进行推导类型
func variableTypeDeduction() {
	var a, b, c, d = 3, 4, true, "def"
	fmt.Println(a, b, c, d)
}

// 还可以不使用var，直接使用:=
func variableShorter() {
	a, b, c, d := 3, 4, true, "def"
	b = 5
	fmt.Println(a, b, c, d)
}

// 验证欧拉函数
func euler() {
	fmt.Printf("%.3f %.3f\n",
		cmplx.Exp(1i*math.Pi)+1,
		cmplx.Pow(math.E, 1i*math.Pi)+1)
}

// 验证类型转换
func tryangle() {
	var a, b = 3, 4
	var c int
	c = int(math.Sqrt(float64(a*a + b*b)))
	fmt.Println(c)
}

// 常量定义
func consts() {
	// 常量可以规定类型，也可以不规定类型，不规定类型时，长度是不确定的
	// 常量不一定要大写，因为大小写在Go中是有含义的，首字母大写在Go语言中代表public
	const (
		filename = "abc.txt"
	)
	const a, b = 3, 4
	var c int
	// 不指定类型时，const常量定义的值就是一个文本，不需要强转。
	c = int(math.Sqrt(a*a + b*b))
	fmt.Println(filename, c)
}

// 枚举通过const块定义，通过iota实现一个枚举自增值
func enums() {
	const (
		cpp = iota
		_
		python
		golang
		javascript
	)

	// b, kb, mb, gb, tb, pb
	const (
		b = 1 << (10 * iota)
		kb
		mb
		gb
		tb
		pb
	)

	fmt.Println(cpp, javascript, python, golang)
	fmt.Println(b, kb, mb, gb, tb, pb)
}

func main() {
	fmt.Println("hello world")
	variableZeroValue()
	variableInitialValue()
	variableTypeDeduction()
	variableShorter()
	fmt.Println(aa, ss, cc, dd, ee)
	euler()
	tryangle()
	consts()
	enums()
}
